package org.hhf.rpt.domain;

import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author haohaifeng
 * @date 2021/1/22 13:56
 */
@Slf4j
@Component
public class PageSupport {
    @Resource
    private JdbcTemplate jdbcTemplate;


    public Object selectOne(String sql, Object[] params, Class cla) {
        Object result = null;
        try {
            if (params == null || params.length > 0) {
                result = jdbcTemplate.queryForObject(sql, cla, params);
            } else {
                result = jdbcTemplate.queryForObject(sql, cla);
            }
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
        }
        return result;
    }

    /**
     * 查询返回List<Map<String,Object>>格式数据,每一个Map代表一行数据，列名为key
     *
     * @param sql    sql语句
     * @param params 填充问号占位符数
     * @return
     */
    public List<Map<String, Object>> queryForMaps(String sql, Object[] params) {
        try {
            if (params != null && params.length > 0) {
                return jdbcTemplate.queryForList(sql, params);
            }
            return jdbcTemplate.queryForList(sql);
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
        }
        return null;
    }

    /**
     * 查询返回实体对象集合
     *
     * @param sql    sql语句
     * @param params 填充sql问号占位符数
     * @param cla    实体对象类型
     * @return
     */
    public List queryForObjectList(String sql, Object[] params, final Class cla) {
        final List list = new ArrayList();
        try {
            jdbcTemplate.query(sql, new RowCallbackHandler() {
                @Override
                public void processRow(ResultSet rs) {
                    try {
                        List<String> columnNames = new ArrayList<String>();
                        ResultSetMetaData meta = rs.getMetaData();
                        int num = meta.getColumnCount();
                        for (int i = 0; i < num; i++) {
                            columnNames.add(meta.getColumnLabel(i + 1).toLowerCase().trim());
                        }
                        Method[] methods = cla.getMethods();
                        List<String> fields = new ArrayList<String>();
                        for (int i = 0; i < methods.length; i++) {
                            if (methods[i].getName().trim().startsWith("set")) {
                                String f = methods[i].getName().trim().substring(3);
                                f = (f.charAt(0) + "").toLowerCase().trim() + f.substring(1);
                                fields.add(f);
                            }
                        }
                        do {
                            Object obj = null;
                            try {
                                obj = cla.getConstructor().newInstance();
                            } catch (Exception ex) {
                                log.error(ex.getMessage(), ex);
                            }
                            for (int i = 0; i < num; i++) {
                                Object objval = rs.getObject(i + 1);
                                for (int n = 0; n < fields.size(); n++) {
                                    String fieldName = fields.get(n).trim();
                                    if (columnNames.get(i).equals(fieldName.toLowerCase().trim())) {
                                        Field f = obj.getClass().getDeclaredField(fieldName);
                                        f.setAccessible(true);
                                        f.set(obj, objval);
                                        break;
                                    }
                                }
                            }
                            list.add(obj);
                        } while (rs.next());
                    } catch (Exception ex) {
                        log.error(ex.getMessage(), ex);
                    }
                }
            }, params);
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
        }
        if (list.size() <= 0) {
            return null;
        }
        return list;
    }

    /**
     * 分页查询.
     */
    public PageBean queryByPage(String sql, PageBean page) {
        return queryByPage(sql, null, page, null);
    }

    /**
     * 分页查询.
     */
    public PageBean queryByPage(String sql, PageBean page, Class clazz) {
        return queryByPage(sql, null, page, clazz);
    }

    /**
     * 查询分页（MySQL数据库）
     */
    public PageBean queryByPage(String sql, Object[] params, PageBean page, Class clazz) {
        int pageNum = page.getPageNo();
        int pageSize = page.getPageSize();
        String rowsql = "select count(*) from (" + sql + ") t";   //查询总行数sql
        int pages = 0;   //总页数
        int rows = (Integer) selectOne(rowsql, params, Integer.class);  //查询总行数
        //判断页数,如果是页大小的整数倍就为rows/pageRow如果不是整数倍就为rows/pageRow+1
        if (rows % pageSize == 0) {
            pages = rows / pageSize;
        } else {
            pages = rows / pageSize + 1;
        }
        //查询第pageNum页的数据sql语句
        if (pageNum <= 1) {
            sql += " limit 0," + pageSize;
        } else {
            sql += " limit " + ((pageNum - 1) * pageSize) + "," + pageSize;
        }
        //查询第pageNum页数据
        List list = null;
        if (clazz != null) {
            list = queryForObjectList(sql, params, clazz);
        } else {
            list = queryForMaps(sql, params);
        }
        //设置总记录数
        page.setTotal(rows);
        //设置总页数
        page.setPages(pages);
        //设置当前页数据
        page.setList(list);
        //设置当前页记录数
        page.setSize(list.size());
        return page;
    }
}
